package com.huiquan.icd.service;

import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.StringUtils;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.ModelAndView;

import com.huiquan.analysis.domain.User;
import com.huiquan.framework.base.BaseService;
import com.huiquan.framework.base.ReturnCode;
import com.huiquan.framework.base.ReturnData;
import com.huiquan.framework.utils.GetListUtil;
import com.huiquan.framework.utils.RespHeaderUtil;
import com.huiquan.framework.utils.ReturnUtil;
import com.huiquan.icd.dao.IcdDiseaseSymptomBlackDao;
import com.huiquan.icd.dao.IcdDiseaseSymptomDao;
import com.huiquan.icd.domain.IcdDiseaseSymptomBlack;
import com.huiquan.synonymy.dao.SynonymyWordDao;

@Service
public class IcdDiseaseSymptomBlackService extends BaseService {

	@Autowired
	private IcdDiseaseSymptomBlackDao icdDiseaseSymptomBlackDao;
	@Autowired
	private IcdDiseaseSymptomDao icdDiseaseSymptomDao;
	@Autowired
	private SynonymyWordDao synonymyWordDao;

	public ModelAndView list(Integer start, String codeSearch, String nameSearch, String exactSearchFlag,
			String checkFlag, String countPerPageStr) {
		boolean exactFlag = exactSearchFlag != null && exactSearchFlag.equals("1");

		Map<String, Object> param = new HashMap<>();
		if (codeSearch != null && !codeSearch.isEmpty()) {
			param.put("disease", exactFlag ? codeSearch : "%" + codeSearch + "%");
		}
		param.put("checkFlag", checkFlag);
		int totalSize = icdDiseaseSymptomBlackDao.retrieveSize(param);

		Map<String, Integer> pageNo = new HashMap<>();
		if (countPerPageStr != null && !countPerPageStr.isEmpty()) {
			int countPerPage = Integer.parseInt(countPerPageStr);
			pageNo = GetListUtil.getPageNoParam(totalSize, start + "", countPerPage);
			param.put("countPerPage", countPerPage);
		} else {
			pageNo = GetListUtil.getPageNoParam(totalSize, start + "");
		}
		int endPage = pageNo.get("endPage");
		start = pageNo.get("start");
		int startIndex = pageNo.get("startIndex");

		List<IcdDiseaseSymptomBlack> list = new ArrayList<>();

		if (startIndex < totalSize) {
			param.put("startIndex", startIndex);
			list = icdDiseaseSymptomBlackDao.retrievesList(param);
		}
		Map<String, String> showSearch = new LinkedHashMap<>();
		showSearch.put("codeSearch", "疾病");

		Map<String, String> searchMap = new HashMap<>();
		searchMap.put("codeSearch", codeSearch);
		searchMap.put("nameSearch", nameSearch);
		Map<String, Object> map = GetListUtil.getReturnMap2(totalSize, start, startIndex, endPage, list, searchMap);
		map.put("showSearch", showSearch);
		map.put("showSearchValue", searchMap);
		map.put("checkFlag", checkFlag);
		map.put("exactSearchFlag", exactSearchFlag);
		return new ModelAndView("icd/index", map);
	}

	public void export(HttpServletResponse resp) throws Exception {
		// 初始化疾病标准名称，和元素标准名称
		icdDiseaseSymptomBlackDao.initStd();
		Map<String, Object> param = new HashMap<>();
		param.put("checkFlag", "0");
		// 获取已校验code列表
		List<IcdDiseaseSymptomBlack> codeList = icdDiseaseSymptomBlackDao.retrievesList(param);
		LOGGER.info("symptomBlackExport get list success!size=" + codeList.size());

		// 设置respons的头信息
		RespHeaderUtil.setXlsxResp(resp, "diseaseSymptomBlack");

		// 创建文档
		XSSFWorkbook workbook = new XSSFWorkbook();
		Sheet sheet = workbook.createSheet("diseaseSymptomBlack"); // 创建Sheet

		// 循环写入数据
		IcdDiseaseSymptomBlack code = null;
		Row row = null;
		for (int i = 0; i < codeList.size(); i++) {
			code = codeList.get(i);

			row = sheet.createRow(i);

			List<String> cellValues = new ArrayList<>();
			cellValues.add(code.getDiseaseName());
			cellValues.add(code.getDiseaseStd());
			cellValues.add(code.getSymptom());
			cellValues.add(code.getVocabulary());
			cellValues.add(code.getProperty());
			cellValues.add(code.getProbability());
			cellValues.add(code.getLift());
			cellValues.add(code.getBlackFlag() + "");
			cellValues.add(code.getCheckFlag() + "");
			addCell(row, cellValues);
		}
		LOGGER.info("symptomBlackExport create excel success!");

		OutputStream os = resp.getOutputStream();
		workbook.write(os);
		workbook.close();

		os.close();
	}

	private void addCell(Row row, List<String> cellValues) {
		if (cellValues.size() > 0) {
			Cell cell = null;
			for (int i = 0; i < cellValues.size(); i++) {
				String cellValue = cellValues.get(i);
				cell = row.createCell(i);
				cell.setCellValue(cellValue);
			}
		}
	}

	@SuppressWarnings("resource")
	public ReturnData diseaseImport(MultipartFile mFile, User user) throws Exception {

		// 获取文件流，解析文件
		InputStream inputStream = mFile.getInputStream();

		Workbook workbook = new XSSFWorkbook(inputStream);
		Sheet sheet = workbook.getSheetAt(0);
		// 已校验记录
		List<IcdDiseaseSymptomBlack> updateList = new ArrayList<>();
		// 更新为白名单症状记录
		List<IcdDiseaseSymptomBlack> whiteList = new ArrayList<>();

		// 初始化疾病标准名称，和元素标准名称
		icdDiseaseSymptomBlackDao.initStd();

		Map<String, Map<String, String>> synonymyMap = getSynonymyMap();

		// 获取数据
		ReturnData rtn = getSheelData(whiteList, updateList, sheet);

		if (rtn != null) {
			return rtn;
		}
		// 更新为白名单的,需要把该疾病的元素都更新为白名单
		if (whiteList != null && whiteList.size() > 0) {
			for (IcdDiseaseSymptomBlack white : whiteList) {
				String[] vocabArr = white.getVocabulary().split(",");
				String[] propertyArr = white.getProperty().split(",");
				for (int k = 0; k < vocabArr.length; k++) {
					String vocab = synonymyMap.get(propertyArr[k]).get(vocabArr[k]) != null
							? synonymyMap.get(propertyArr[k]).get(vocabArr[k]) : vocabArr[k];
					// 根据疾病名,元素名修改疾病元素黑名单到白名单
					icdDiseaseSymptomDao.updateByNameVocab(
							synonymyMap.get("di").get(white.getDiseaseName()) != null
									? synonymyMap.get("di").get(white.getDiseaseName()) : white.getDiseaseName(),
							vocab, propertyArr[k],user.getUserId());
				}
				white.setModifierId(user.getUserId());
				white.setCheckFlag(1);
				white.setBlackFlag(0);
				icdDiseaseSymptomBlackDao.update(white);
			}
		}

		if (updateList != null && updateList.size() > 0) {
			for (IcdDiseaseSymptomBlack update : updateList) {
				update.setModifierId(user.getUserId());
				update.setCheckFlag(1);
				icdDiseaseSymptomBlackDao.update(update);
			}
		}

		workbook.close();
		inputStream.close();

		return ReturnUtil.success();
	}

	private ReturnData getSheelData(List<IcdDiseaseSymptomBlack> whiteList, List<IcdDiseaseSymptomBlack> updateList,
			Sheet sheet) {
		// 行数
		int j = 1;
		for (Row row : sheet) {
			int i = 0;
			IcdDiseaseSymptomBlack value = new IcdDiseaseSymptomBlack();
			// 取出每一行记录
			for (Cell cell : row) {
				cell.setCellType(Cell.CELL_TYPE_STRING);
				String word = cell.getStringCellValue().trim();
				if (!word.isEmpty()) {
					switch (i) {
					case 0:
						value.setDiseaseName(word);
						break;
					case 1:
						value.setDiseaseStd(word);
						break;
					case 2:
						value.setSymptom(word);
						break;
					case 3:
						value.setVocabulary(word);
						break;
					case 4:
						value.setProperty(word);
						break;
					case 7:
						if (StringUtils.isNumericSpace(word)) {
							value.setBlackFlag(Integer.parseInt(word));
						} else {
							ReturnCode rc = ReturnCode.DYNAMIC_DESC_EXCEPTION;
							rc.setDesc("第" + j + "行,第" + (i + 1) + "列,格式有误");
							return ReturnUtil.fail(rc);
						}
						break;
					case 8:
						if (StringUtils.isNumericSpace(word)) {
							value.setCheckFlag(Integer.parseInt(word));
						} else {
							ReturnCode rc = ReturnCode.DYNAMIC_DESC_EXCEPTION;
							rc.setDesc("第" + j + "行,第" + (i + 1) + "列,格式有误");
							return ReturnUtil.fail(rc);
						}
						break;
					default:
						break;
					}
				}
				i++;
			}
			if (value.getCheckFlag() == 1) {
				if (value.getBlackFlag() == 0) {
					whiteList.add(value);
				} else {
					updateList.add(value);
				}
			}
			j++;
		}
		return null;
	}

	private Map<String, Map<String, String>> getSynonymyMap() {
		Map<String, Map<String, String>> synonymyMap = new HashMap<>();
		List<Map<String, String>> oSynonymys = synonymyWordDao.retrieveElementSynonymByProperty("o");
		Map<String, String> oWord = new HashMap<>();
		for (Map<String, String> oSynonymy : oSynonymys) {
			oWord.put(oSynonymy.get("word"), oSynonymy.get("std"));
		}
		synonymyMap.put("o", oWord);
		List<Map<String, String>> sSynonymys = synonymyWordDao.retrieveElementSynonymByProperty("s");
		Map<String, String> sWord = new HashMap<>();
		for (Map<String, String> sSynonymy : sSynonymys) {
			sWord.put(sSynonymy.get("word"), sSynonymy.get("std"));
		}
		synonymyMap.put("s", sWord);
		List<Map<String, String>> siSynonymys = synonymyWordDao.retrieveElementSynonymByProperty("si");
		Map<String, String> siWord = new HashMap<>();
		for (Map<String, String> siSynonymy : siSynonymys) {
			siWord.put(siSynonymy.get("word"), siSynonymy.get("std"));
		}
		synonymyMap.put("si", siWord);
		List<Map<String, String>> diSynonymys = synonymyWordDao.retrieveElementSynonymByProperty("di");
		Map<String, String> diWord = new HashMap<>();
		for (Map<String, String> diSynonymy : diSynonymys) {
			diWord.put(diSynonymy.get("word"), diSynonymy.get("std"));
		}
		synonymyMap.put("di", diWord);
		return synonymyMap;
	}

	public ReturnData changeBlackFlag(Long id, String blackFlag, String checkFlag, User user) {
		icdDiseaseSymptomBlackDao.updateBlackFlag(id, blackFlag,user.getUserId());
		if (StringUtils.equalsIgnoreCase(checkFlag, "1") && StringUtils.equalsIgnoreCase(blackFlag, "0")) {
			// 更新该ID下的所有元素到白名单
			updateSymptom(id,user);
		}
		return ReturnUtil.success();
	}
	
	public ReturnData submit(Long id, User user) {
		icdDiseaseSymptomBlackDao.updateCheckFlag(id,user.getUserId());
		IcdDiseaseSymptomBlack value = icdDiseaseSymptomBlackDao.retrieveObjectById(id);
		if(value.getBlackFlag() == 0){
			// 更新该ID下的所有元素到白名单
			updateSymptom(id,user);
		}
		return ReturnUtil.success();
	}
	
	
	public ReturnData init() {
		// 初始化疾病标准名称，和元素标准名称
		icdDiseaseSymptomBlackDao.initStd();
		return ReturnUtil.success();
	}
	
	public synchronized void updateSymptom(Long id,User user){
		// 需要修改元素为白名单
		IcdDiseaseSymptomBlack value = icdDiseaseSymptomBlackDao.retrieveObjectById(id);
		String[] vocabArr = value.getVocabulary().split(",");
		String[] propertyArr = value.getProperty().split(",");
		for (int k = 0; k < vocabArr.length; k++) {
			// 根据疾病名,元素名修改疾病元素黑名单到白名单
			icdDiseaseSymptomDao.updateByNameVocab(value.getDiseaseStd(), vocabArr[k], propertyArr[k],user.getUserId());
		}
	}
	
}
